﻿/*

(c) Sense Studios 2008
Sense Studios (http://www.sense-studios.com) all rights reserverd
Part of Canvas, NLtracks
_________     _____    ___________   _________    _________
\_   ___ \   /  _  \   \      \   \ /   /  _  \  /   _____/
/    \  \/  /  /_\  \  /   |   \   Y   /  /_\  \ \_____  \ 
\     \____/    |    \/    |    \     /    |    \/        \
 \______  /\____|__  /\____|__  /\___/\____|__  /_______  /
        \/         \/         \/              \/        \/ 
		
 # The Canvas Class is the collection of ALL interaction functions
 of the canvas, the mousinterface, the background builders and the
 cursors. Also it can set GoTo and CenterOn command.
 
 Usage:
 public functions include, but are not limited to:
	###  GoTo(X, Y)
	###  CenterOn(X, Y)
	
 Also check out Wii-canvas, for Wii controls.
 
 The MatrixCanvas is exactly the same as a normal Canvas, only
 it uses matrix calulations to do it's thing
 
 It seems that the original snapping functions are still present in this one
 
*/

package com.sense.canvas { 

	import flash.display.*
	import flash.events.*
	import flash.text.*
	import flash.geom.*
	import flash.ui.Mouse;
	import flash.net.*
	import flash.geom.Matrix;
	import flash.system.Security;
	import flash.utils.Timer
	
	// for zip files
	import com.sense.utils.fzip.FZip
	import com.sense.utils.fzip.FZipFile
	
	import com.sense.utils.BitmapManipulator
	
	public class MatrixCanvas extends MovieClip {

		public var template:Object
		public var Controller
		
		private var fullBrowser:String = "false"
		private var doSnapping:String = "false"
		
		private var gridX:int
		private var gridY:int
		
		private var sizeX:int
		private var sizeY:int
		private var winX:int = 0
		private var winY:int = 0
		private var winW:int = 0
		private var winH:int = 0

		private var vx:Number = 0
		private var vy:Number = 0
		public var setX:int = 0
		public var setY:int = 0
		private var oldX:int = 0
		private var oldY:int = 0
		
		private var snapping:Boolean = false
		private var snapXisSet = false
		private var snapYisSet = false
		
		private var background_image:String
		private var background_image_width:int
		private var background_image_height:int
		
		private var snapX:int = 0
		private var snapY:int = 0
		private var startX:int = 0
		private var startY:int = 0
		
		private var gX:Number = 0
		private var gY:Number = 0
	
		private var fr:Number = 0
		private var eas:Number = 0
		private var bounceFriction:Number = 0
		private var mouseWheelMultiplyer:int = 0
				
		public var puls:int = 0
		private var border:int = 0
		
		public var border_cursor:MovieClip
		public var move_cursor:MovieClip
		public var onHud:Boolean = false
		public var borderContainer:MovieClip = new MovieClip()
		private var velocityCounter:int = 0
		private var bitmapped:Boolean = false
		
		// ==== really private ==== :p
		
		private var mousePlace:String = null
		private var allowedObjects:Number = 2
		
		public var allContainer:MovieClip
		public var hideContainer:MovieClip

		private var background:MovieClip
		
		public var borderShape:Shape = new Shape()
		private var affineTransform:Matrix

		private var bmpMinSpeed:Number = 0.01
		private var bmpMaxSpeed:Number = 6
		
		private var dx:int
		private var dy:int
		private var newX:Number
		private var newY:Number
		
		private var greyedOut:MovieClip
		private var loadingIsSet:Boolean = false
		
		private var safeMargin:int = 8
		
		private var zoomTimer:Timer
		
		private var globalReference
	
		private var scale:Number = 1
	
		public function MatrixCanvas():void {
			trace("constructing MATRIXXX canvas")
			init()
		}
		
		private function init() {
			//background.buttonMode = true
			this.name = "canvas"
			addEventListener(MouseEvent.MOUSE_OVER, doMouseOver)
			addEventListener(MouseEvent.MOUSE_OUT, doMouseOut)
			addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown)
			addEventListener(MouseEvent.MOUSE_WHEEL, doMouseWheel)
			addEventListener(Event.ENTER_FRAME, doMove)
			addEventListener(Event.ADDED_TO_STAGE, onAdded)
		}
		
		private function onAdded(evtObj:Event) {
						
			// stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler) // for CTRL + SHIFT + DOUBLE DOT + ESC;
			stage.addEventListener(KeyboardEvent.KEY_UP, keyUpHandler);
			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler);
			border_cursor = new move_arrow()
			border_cursor.name = "border_cursor"
			border_cursor.visible = false
			border_cursor.mouseEnabled = false
			stage.addChild(border_cursor)

			move_cursor = new move_cirkle()
			move_cursor.name = "move_cursor"
			stage.addChild(move_cursor)
			move_cursor.visible = false
			move_cursor.mouseEnabled = false
			
			// border interaction so we don't have to loop it
			parent.addChild(borderContainer)
			borderContainer.addChild(borderShape)
			borderContainer.addEventListener(MouseEvent.MOUSE_OVER, doCheckBorder)
			borderContainer.addEventListener(MouseEvent.MOUSE_OUT, unCheckBorder)
			borderContainer.addEventListener(MouseEvent.CLICK, doPulse)
			
			allContainer = new MovieClip()
			addChild(allContainer)
			
			// truck de la truck --> optimizing
			// hideContainer = new MovieClip()
			// hideContainer.name = "background" // so we can continue to drag
			// addChild(hideContainer)
			// hideContainer.visible = false
			
			trace("canvas full browser mode is set")
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.addEventListener(Event.RESIZE, doOnResize)
			stage.addEventListener(Event.ENTER_FRAME, doMouse)
			
			zoomTimer = new Timer(2000, 1)
			zoomTimer.addEventListener("timer", doZoomOut)
			
			globalReference = stage.getChildByName("globals")
		}
		
		private function doOnResize(evtObj:Event) {
			//trace("canvas resize!")
			winW = stage.stageWidth
			winH = stage.stageHeight
			drawBorder()
		}
		
		public function setController(controller) {
			this.Controller = controller
		}
		
		public function setTemplate(template) {
			if (!loadingIsSet) {
				this.template = template
				
				//clean up
				var childLength:int = allContainer.numChildren-1
				for (var i = childLength; i > -1; i--) {
					trace("removing child: ", allContainer.getChildAt(0), i, allContainer.numChildren)
					allContainer.removeChildAt(0)
				}
								
				// setLoading()
				setParams()
				drawBackground()
				doOnResize(null)	
			}
		}
		
		private function setParams() {
			this.fullBrowser = template.fullBrowser
			this.doSnapping = template.doSnapping
			this.gX = template.gridX
			this.gY = template.gridY
			this.sizeX = template.sizeX
			this.sizeY = template.sizeY
			this.winX = template.winX
			this.winY = template.winY
			this.winW = template.winW
			this.winH = template.winH
			this.fr = template.friction
			this.eas = template.easing
			this.puls = template.puls
			this.border = template.border
			this.background_image = template.background_image
			this.background_image_width = template.background_image_width
			this.background_image_height = template.background_image_height
			this.bounceFriction = template.bounceFriction
			this.mouseWheelMultiplyer = template.mouseWheelMultiplyer

			// starting point
			this.startX = template.startX
			this.startY = template.startY
		}
		
		public function updateBackGround(bgrImage, bgrWidth, bgrHeight) {
			//clean up
			var childLength:int = allContainer.numChildren-1
			for (var i = childLength; i > -1; i--) {
				trace("removing child: ", allContainer.getChildAt(0), i, allContainer.numChildren)
				allContainer.removeChildAt(0)
			}
				
			this.background_image = bgrImage
			this.background_image_width = bgrWidth
			this.background_image_height = bgrHeight
			drawBackground()
		}
		
		private function drawBorder() {
			borderShape.graphics.clear()
			borderShape.graphics.beginFill(0x000000, 0)
			borderShape.graphics.lineStyle(0, 0x00000, 0)
			borderShape.graphics.drawRect(winX, winY, winW, winH)
			borderShape.graphics.drawRect(winX + border, winY+border, winW-(border*2), winH-(border*2))
		}
		
		private function setLoading() { // no longer used
			
			if (!loadingIsSet) {
				loadingIsSet = true
				greyedOut = new MovieClip()
				stage.addChild(greyedOut)
				
				var cxLength:int = Math.ceil(stage.stageWidth/78) + 1
				var cyLength:int = Math.ceil(stage.stageHeight/78) + 1
				
				for (var cx:int = 0; cx < cxLength; cx++) {
					for (var cy:int = 0; cy < cyLength; cy++) {
						var load_bg_tile = new load_bg()
						load_bg_tile.x = cx * 78
						load_bg_tile.y = cy * 78
						greyedOut.addChild(load_bg_tile)
					}
				}
			}
		}
		
		private function removeLoading() {
			if (loadingIsSet) {
				stage.removeChild(greyedOut)
				goTo(startX, startY)
				loadingIsSet = false
			}
		}
		
		private function drawBackground():void {
			
			// create background object
			background = new MovieClip()
			allContainer.addChild(background)
			
			background.name = "background"
			background.isDraggable = true
			
			// firstDraw some framework
			background.graphics.beginFill(0x333333, 0.3);
			background.graphics.drawRect(0, 0, this.sizeX, this.sizeY);		

			var cxLength:int = Math.ceil(sizeX/gX)
			var cyLength:int = Math.ceil(sizeY/gY)
			
			for (var cx = 0; cx < cxLength; cx++) {
				for (var cy = 0; cy < cyLength; cy++) {
					var cross:Sprite = new Sprite();
					cross.name = "cross_" + cx + "_" + cy
					cross.graphics.lineStyle(1, 0x666666, 1)
					
					cross.graphics.moveTo ( cx*gX, (cy*gY) -3 )
					cross.graphics.lineTo ( cx*gX, (cy*gY) +4 )
					cross.graphics.moveTo ( (cx*gX)-3, (cy*gY) )
					cross.graphics.lineTo ( (cx*gX)+4, (cy*gY) )
					
					background.addChild(cross)
				}
			}
			
			if (template.background_image) {
				
				var fileFromZip:FZipFile = globalReference.stylingZip.getFileByName( background_image )
				var bgrLoader:Loader = new Loader()
				bgrLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, doLoadComplete)
				bgrLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
				// bgrLoader.load( new URLRequest(background_image) )
				bgrLoader.loadBytes(fileFromZip.content);
				
				function doLoadComplete(e:Event) {
					var cxLength:int = Math.ceil(sizeX / background_image_width)
					var cyLength:int = Math.ceil(sizeY / background_image_height)
					
					for (var cx:int = 0; cx < cxLength; cx++) {
						for (var cy:int = 0; cy < cyLength; cy++) {
							var bgrBitmap = mcToBitmap(bgrLoader, true, 0, 0, background_image_width, background_image_height, 1)							
							bgrBitmap.name = "background"
							bgrBitmap.x = cx * background_image_width
							bgrBitmap.y = cy * background_image_height
							background.addChild(bgrBitmap)
						}
					}
					
					//removeLoading() 
					trace("Canvas dispatched complete")
					dispatchEvent(new Event(Event.COMPLETE))
				}
				
			}else if (template.backgroundImageGroup) {

				template.backgroundImageGroup.forEach(buildImage)
				var count:int = 0
				
				function buildImage(element, i, a) {
					trace(element, element.url, globalReference)
					
					var bgrLoader:Loader = new Loader()
					var fileFromZip:FZipFile = globalReference.stylingZip.getFileByName( element.url )
					
					var bgrLoader:Loader = new Loader()
					
					// bgrLoader.load(new URLRequest( fileFromZip.content ))
					bgrLoader.loadBytes(fileFromZip.content)
					bgrLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, doLoadComplete)
					bgrLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
					
					function doLoadComplete(e:Event) {
						
						//var bgrBitmap = BitmapManipulator.simpleMcToBitmap(bgrLoader)
						//bgrLoader.name = "background"
						//bgrLoader.x = element[1]
						//bgrLoader.y = element[2]
						//background.addChild(bgrBitmap)
						//background.addChild(bgrLoader)
						
						var bgrBitmap = BitmapManipulator.simpleMcToBitmap(bgrLoader)
						bgrBitmap.name = "background"
						bgrBitmap.x = element.x
						bgrBitmap.y = element.y
						background.addChild(bgrBitmap)
						
						count ++
						
						if (count == template.backgroundImageGroup.length) {
							trace("Canvas dispatched complete")
							dispatchEvent(new Event(Event.COMPLETE))
						}
					}
				}
			}
		}
		
		private function ioErrorHandler(e:Event) {
			trace("ERROR: CANVAS had load error ", e)
		}
		
		private function doCheckBorder(evtObj:Event) {
			border_cursor.visible = true
			Mouse.hide()
			addEventListener(Event.ENTER_FRAME, checkBorder)
		}
		
		private function unCheckBorder(evtObj:Event) {
			border_cursor.visible = false
			Mouse.show()
			removeEventListener(Event.ENTER_FRAME, checkBorder)
		}
		
		private function checkBorder(evtObj:Event) {
			
			if (stage.mouseX > winX && stage.mouseX < winW && stage.mouseY > winY && stage.mouseY < winH) {
				
				if (stage.mouseY < (winY + border) && stage.mouseX < (winX + border) ) { // up/left
					mousePlace = "upleft"
					Mouse.hide()
					border_cursor.rotation = -135
					border_cursor.visible = true
					move_cursor.visible = false
				} else if (stage.mouseY < (winY + border) && stage.mouseX > (winW - border)) { // up/right
					mousePlace = "upright"
					Mouse.hide()
					border_cursor.rotation = -45
					border_cursor.visible = true
					move_cursor.visible = false
				} else if (stage.mouseY > (winH - border) && stage.mouseX < (winX + border)) { // down/left
					mousePlace = "downleft"
					Mouse.hide()
					border_cursor.rotation = 135
					border_cursor.visible = true
					move_cursor.visible = false
				} else if (stage.mouseY > (winH - border) && stage.mouseX > (winW - border)) { // down/right 
					mousePlace = "downright"
					Mouse.hide()
					border_cursor.rotation = 45
					border_cursor.visible = true
					move_cursor.visible = false
				} else if (stage.mouseY < (winY + border)) { // up
					allowedObjects = 3
					mousePlace = "up"
					Mouse.hide()
					border_cursor.rotation = -90
					border_cursor.visible = true
					move_cursor.visible = false
				}else if (stage.mouseY > (winH - border)) { // down
					mousePlace = "down"
					Mouse.hide()
					border_cursor.rotation = 90
					border_cursor.visible = true
					move_cursor.visible = false
					move_cursor.visible = false
				}else if (stage.mouseX < (winX + border)) { // left
					allowedObjects = 3
					mousePlace = "left"
					Mouse.hide()
					border_cursor.rotation = 180
					border_cursor.visible = true
					move_cursor.visible = false
				}else if (stage.mouseX > (winW - border)) { // right
					mousePlace = "right"
					Mouse.hide()
					border_cursor.rotation = 0
					border_cursor.visible = true
					move_cursor.visible = false
				}else{
					mousePlace = null
					border_cursor.rotation = 0
					border_cursor.visible = false
					if (!move_cursor.visible) {
						Mouse.show()
					}
				}
			}else{
				trace("not true")
				
				mousePlace = null
				border_cursor.rotation = 0
				border_cursor.visible = false
				
				if (!move_cursor.visible) {
					Mouse.show()
				}
			}
		}
				
		private function doMouseWheel(evtObj:Event) {
			var mw_move:int = evtObj["delta"] * mouseWheelMultiplyer
			//trace(mw_move)
			goTo(x, y + mw_move)
		}

		// dragging cursor
		private function doMouseOver(evtObj:Event) {
			
			if (evtObj.target.name == "background") {
				Mouse.hide()
				move_cursor.visible = true
				move_cursor.gotoAndStop(1)
				trace("Set cursor")
			}else{
				Mouse.show()
				move_cursor.visible = false
			}
		}
		
		// remove dragging cursor
		private function doMouseOut(evtObj:Event) {
			// trace("remove cursor")
			Mouse.show()
			move_cursor.visible = false
		}
		
		private function doMouseDown(evtObj:Event) {
			if (evtObj.target.name == "background") {
				
				Mouse.hide()
				move_cursor.visible = true
				move_cursor.gotoAndStop(2)
				
				// start tracking velocity for throwing
				removeEventListener(MouseEvent.MOUSE_DOWN, doMouseDown)
				removeEventListener(Event.ENTER_FRAME, doMove)
				
				addEventListener(Event.ENTER_FRAME, trackVelocity)
				stage.addEventListener(MouseEvent.MOUSE_UP, doMouseUp)
				stage.addEventListener(Event.MOUSE_LEAVE, doMouseUp)
	
				snapping = false
				//setSnapShot()
				dx = 0
				dy = 0
				startDrag()
			}
		}
		
		private function doMouseUp(evtObj:Event) {
			stopDrag()
			Mouse.show()
			move_cursor.visible = false
			
			stage.removeEventListener(MouseEvent.MOUSE_UP, doMouseUp)
			removeEventListener(Event.ENTER_FRAME, trackVelocity)
			
			addEventListener(MouseEvent.MOUSE_DOWN, doMouseDown)
			addEventListener(Event.ENTER_FRAME, doMove)
		}
		
        private function keyUpHandler(event:KeyboardEvent):void {
           	trace("keyUpHandler: " + event.keyCode);
			
			// Public held keys (from template)
			/*
			for (var i=0; i < template.markers.length; i++) {
				if (event.keyCode == template.markers[i].key) {
					trace("found marker: ", template.markers[i].name)
					goTo(-template.markers[i].x, -template.markers[i].y)
				}
			}
			*/
			
			// Private held keys
			switch (event.keyCode) {

				case (38):  // "up"
					goTo(setX, setY+puls)
					break;

				case (37): // "left"
					goTo(setX + puls, setY)
					trace("left")
					break;
				
				case (39): // "right"
					goTo(setX - puls, setY)
					break;

				case (40): // "down"
					goTo(setX, setY-puls)				
					break;
				
				case (50):
					// takeSnapShot()
					// scaleDown()
					break;
				
				case (85): //u
					// 
					break;
				
				case (36): // home
					// scaleUp()
					resetScale()
					break;
					
				case (32): // space
					// reset scale
					// scaleDown()
					break;

				case (33): // "zoomin, pageup"
					// scaleAt(1.06, stage.stageWidth/2, stage.stageHeight/2)
					// scaleAt(0.98, mouseX, mouseY)//- setX + (stage.stageWidth/2), - setY + (stage.stageHeight/2))
					scaleUp()
					break;

				case (34): // "zoomout, pagedown"
					// scaleAt(0.94, stage.stageWidth/2, stage.stageHeight/2)
					// scaleAt(1.02, mouseX, mouseY)// - setX + (stage.stageWidth/2), - setY + (stage.stageHeight/2))
					scaleDown()
					break;

				default:
					break;
			}
        }
		
		private function keyDownHandler(event:KeyboardEvent):void {
			//trace("key Down handler")
			switch (event.keyCode) {
				case (32):
					//scaleAt(1/currentScale, 0, 0)
					break;
				
				case (107): // 107 +
					//scaleAt(1/currentScale, 0, 0)
					scale = 1 / 0.85 //1.05
					break
				
				case (109): //-
					//scaleAt(1/currentScale, 0, 0)
					scale = 0.85
					break
			}
		}
		
		// ## zoom functionality ##
		
		private function doZoomOut(e:Event) {
		}
		
		private function scaleUp(e:Event=null) {
			/*
			trace("scaleUp")
			removeEventListener(MouseEvent.CLICK, scaleUp)
			 
			var scaleSpeed:Number = 1
			var scaleFriction:Number = 1.02
			addEventListener(Event.ENTER_FRAME, doScaleUp)
			
			function doScaleUp(e:Event) {
				 trace("scaleing up, ", scaleSpeed, currentScale)
				 scaleSpeed *= scaleFriction
				 
				 scaleAt( scaleSpeed , 0, 0 )
				 
				 trace(scaleSpeed)
				 
				 if (width > 6000) {
					 resetScale()
					 removeEventListener(Event.ENTER_FRAME, doScaleUp)
				 }
			}
			*/
		}
		
		// origins seem to be not working :-/
		private function scaleDown(speed:Number = 1.04, friction:Number = 0.99) {
			/*
			trace("scaledown")
						
			var scaleSpeed:Number = speed
			var scaleFriction:Number = friction
			addEventListener(Event.ENTER_FRAME, doScaleDown)
			
			function doScaleDown(e:Event) {
				 trace("scaleing down")
				 scaleSpeed *= scaleFriction
				 scaleAt( scaleSpeed , 0, 0 )
				 
				 trace(scaleSpeed)
				 
				 if (width < 2000 || height < 2000) {
					 trace("setting double click")
					 removeEventListener(Event.ENTER_FRAME, doScaleDown)
					 removeEventListener(Event.ENTER_FRAME, doMove)
					 doubleClickEnabled = true
					 addEventListener(MouseEvent.CLICK, scaleUp)
				 }
			}
			*/
		}
		
		private function resetScale() {
			/*
			scaleAt(1/currentScale, 0, 0)
			currentScale = 1
			*/
		}
		
		private function scaleAt( scale : Number, originX : Number, originY : Number) : void {
			
			/*
			removeEventListener(Event.ENTER_FRAME, doMove)
			
			var originX = -stage.mouseX
			var originY = -stage.mouseY
			
			trace(originX, allContainer.mouseX, mouseX, stage.mouseX, this.mouseX)
			
			affineTransform = this.transform.matrix;
			affineTransform.translate( -stage.mouseX, -stage.mouseX );
			affineTransform.scale( scale, scale );
			affineTransform.translate( stage.mouseX, stage.mouseY );
			this.transform.matrix = affineTransform;

			currentScale *= scale

			trace(currentScale)
			
			//oldX = x
			//oldY = y
			// centerOn(this.mouseX, this.mouseY)
			// setX = x
			// setY = y
			*/
		}
		
	
		/*
		function scaleAt( scale : Number, originX : Number, originY : Number) : void {
			
			removeEventListener(Event.ENTER_FRAME, doMove)
			
			var origWidth = width
			var origHeight = height

			if (width > stage.stageWidth || height > stage.stageHeight || scale > 0) {
				
				scaleX += scale
				scaleY += scale
								
				x += (origWidth - width)/2
				y += (origHeight - height)/2

			}

		}
		*/
		
		/*
		function scaleAt( scale : Number, originX : Number, originY : Number) : void {
				var ref1:MovieClip = new MovieClip()
				ref1 = this as MovieClip
				
				var myDisplayObject:DisplayObject = this as DisplayObject
				var affineTransform = myDisplayObject.transform.matrix 
				
				var point:Point = new Point(originX, originY)
				affineTransform.transformPoint(point);
				
				//var tempTransform = this.transform.matrix;
				//allContainer.translate( -originX, -originY );
				//affineTransform.scale( scale, scale );
				
				//rotateAroundInternalPoint(affineTransform, originX, originY)
				
				//allContainer.translate( originX, originY )
				//affineTransform.a *= scale;
				//affineTransform.d *= scale;
				//affineTransform.tx *= 10//-scale;
				//affineTransform.ty *= 10//-scale;
				//allContainer.translate
				//allContainer.transform.matrix = affineTransform
				
				//affineTransform.translate(10, 10)
				affineTransform.scale(scale, scale)
				
				
				myDisplayObject.transform.matrix = affineTransform;

				
				//this.x = allContainer.x
				//this.y = allContainer.y
				//this.width *= factor
				//this.height *= factor
				
				trace(allContainer.x, allContainer.y, allContainer.width, allContainer.height)
				trace(this.x, this.y, this.width, this.height)
				trace(ref1.x, ref1.y, ref1.width, ref1.height)
				//this.transform.matrix = allContainer.transform.matrix
				
				
		}
		*/
		
		// ##

		private function doPulse(evtObj:Event) {
			trace("doPulse")
			
			switch (mousePlace) {
				case ("upleft"):  // "upleft"
					goTo(x+puls, y+puls)
					break;

				case ("downleft"): //"left"
					goTo(x+puls, y-puls)
					break;
				
				case ("upright"): //"right"
					goTo(x-puls, y+puls)
					break;

				case ("downright"): // "down"
					goTo(x-puls, y-puls)				
					break;
					
				case ("up"):  // "up"
					goTo(x, y+puls)
					break;

				case ("left"): //"left"
					goTo(x+puls, y)
					break;
				
				case ("right"): //"right"
					goTo(x-puls, y)
					break;

				case ("down"): // "down"
					goTo(x, y-puls)				
					break;
					
				default :
					// trace(evtObj)
					// test goto mouseclick
					// goTo(evtObj["localX"] + (winW/2), -evtObj["localY"] + (winH/2))
			}			
		}

		// Moving functions		
		public function goTo(goX, goY) {
			newX = goX
			newY = goY
			dx = newX - setX
			dy = newY - setY
		}
		
		public function goToslow(goX, goY) {
		}
		
		public function centerOn(goX, goY) {
			newX = goX + (stage.stageWidth/2)
			newY = goY + (stage.stageHeight/2)
			dx = newX - setX
			dy = newY - setY
		}
		
		private function trackVelocity(evtObj:Event) { 
			affineTransform = this.transform.matrix;
			
			// speed is impulz van mouseX en Y
			setX = affineTransform.ty
			setY = affineTransform.ty
			
			vx = setX - oldX
			vy = setY - oldY
			
			oldX = setX
			oldY = setY
			
			// Boundries 
			if (setX > winX) {
				dx = 0
				dy = 0
				doMouseUp(null)
				setX = winX 
			}
			
			if (setY > winY) { 
				dx = 0
				dy = 0
				doMouseUp(null)
				setY = winY 
			}
			
			if (setX < winW - sizeX) { 
				dx = 0
				dy = 0
				doMouseUp(null)
				setX = winW - sizeX 
			}
			
			if (setY < winH - sizeY) { 
				dx = 0
				dy = 0
				doMouseUp(null)
				setY = winH - sizeY 
			}
		}
		
		private function doMove(evtObj:Event) {
			
			affineTransform = this.transform.matrix;
			
			if (doSnapping == "true") {
				// Snapping
				if ( (setX%gX != 0 || setY%gY != 0) && vx > -1 && vx < 1 && vy > -1 && vy < 1 && !snapping ) {  // start snapping
					
					snapping = true
					
					// nearest snap point following the original direction of the move
					if (vx < 0) {
						snapX = Math.round( (setX-(gX * .5))/gX )
					}else{
						snapX = Math.round( (setX+(gX * .5))/gX )					
					}
						
					if (vy < 0) {
						snapY = Math.round((setY-(gY * .5 ))/gY)
					}else{
						snapY = Math.round((setY+(gY * .5 ))/gY)
					}
	
					trace("snap to: " + snapX, snapY)
					
					
					goTo(snapX *gX, snapY*gY)
					
					vx = ( ( snapX * gX ) - setX) * .2 // / 8
					vy = ( ( snapY * gY ) - setY) * .2 // / 8
				}
			}
			
			if (Math.abs(dx) > 0.1 || Math.abs(dy) > 0.1) {
				// use Easing
				dx = newX - setX
				dy = newY - setY
				vx = dx * eas
				vy = dy * eas
			}else{
				// Friction
				vx *= fr
				vy *= fr
			}
			
			// Roundup
			if (Math.abs(vx) < 0.001) {
				vx = 0
			}
			
			if (Math.abs(vy) < 0.001) {
				vy = 0
			}
			
			// Bounce 
			if (setX > winX) {
				dx = 0
				dy = 0
				setX = winX
				vx = -vx * bounceFriction
			}
			
			if (setY > winY) { 
				dx = 0
				dy = 0
				setY = winY
				vy = -vy * bounceFriction
			}
			
			if (setX < winW - sizeX) {
				dx = 0
				dy = 0
				setX = winW - sizeX
				vx = -vx * bounceFriction
			}

			if (setY < winH - sizeY) {
				dx = 0
				dy = 0
				setY = winH - sizeY
				vy = -vy * bounceFriction
			}
	
			if ( ( scale < 0.99 || scale > 1.01 )) {
				
				affineTransform.translate( -stage.mouseX, -stage.mouseY );
				affineTransform.scale( scale, scale );
				affineTransform.translate( stage.mouseX, stage.mouseY );
				dx = 0
				dy = 0
				
				if (scale > 1) {
					scale *= 0.99
				}else{
					scale *= 1.01
				}
			
			}else{
				scale = 1
			}
			
			if (affineTransform.tx > 0) affineTransform.tx = 0
			if (affineTransform.ty > 0) affineTransform.ty = 0
			
			if (affineTransform.tx < ( -width + stage.stageWidth ) ) affineTransform.tx = -width + stage.stageWidth
			if (affineTransform.ty < ( -height + stage.stageHeight ) ) affineTransform.ty = -height + stage.stageHeight

			//if (x > 0) x = 0
			//if (y > 0) y = 0
			//if (x < ( width + x ) ) x = width + x
			//if (y < ( height + y ) ) x = height + y
			
			// Move-Set
			setX += vx
			setY += vy
			
			affineTransform.translate( vx, vy );
			this.transform.matrix = affineTransform;
			
			x = affineTransform.tx
			y = affineTransform.ty
			// Actual Move
			//x = setX
			//y = setY
		}
		
		private function doMouse(e:Event) {
			move_cursor.x = stage.mouseX
			move_cursor.y = stage.mouseY
			border_cursor.x = stage.mouseX
			border_cursor.y = stage.mouseY
			//e.updateAfterEvent()
		}
		
		// small helper function
		private function mcToBitmap(mc, smoothing:Boolean = true, x:Number=0, y:Number=0, w:Number=0, h:Number=0, scale:Number=1):Bitmap {

			// create cropping rectangle and base point
			var rect:Rectangle = new Rectangle(x, y, w, h);
			var pt:Point = new Point(0, 0);
			var original_image:BitmapData = new BitmapData(mc.width, mc.height, true, 0x0000FF)
			var mat:Matrix = new Matrix();
			mat.scale(scale, scale)
			original_image.draw(mc, mat);
			var copyObject:BitmapData = new BitmapData(w-x, h-y, true, 0x0000FF);
			copyObject.copyPixels(original_image, rect, pt)
			var returnBitmap:Bitmap = new Bitmap(copyObject, "auto", smoothing);
			return returnBitmap;
		}
	}
}

